package me.android.library.utils.android;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Build;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowMetrics;

import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;

import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@UtilityClass
public class DisplayUtil {

    /**
     * 获取屏幕高度（不包含通知栏与状态栏）
     */
    public int getHeight_Without_ActionBar_and_NoticationBar(Context cx) {
        int screenHeight = getScreenHeightPixels();
        int acitonbarHeight = (int) getActionBarHeight(cx);
        int noticationbarHeight = (int) getNoticationBarHeight(cx);
        return screenHeight - acitonbarHeight - noticationbarHeight;
    }

    public int getScreenWidthPixels() {
        return ContextUtil.getResources().getDisplayMetrics().widthPixels;
    }

    public int getScreenHeightPixels() {
        return ContextUtil.getResources().getDisplayMetrics().heightPixels;
    }

    public float getActionBarHeight(Context context) {
        AtomicReference<Float> actionBarHeight = new AtomicReference<>((float) 0);

        int[] attrs = new int[]{android.R.attr.actionBarSize};
        TypedArrayUtil.obtainStyledAttrs(context, attrs, typedArray -> {
            actionBarHeight.set(typedArray.getDimension(0, 0));
        });

        return actionBarHeight.get();
    }


    /**
     * 获取通知栏（状态栏）的高度
     *
     * @return 状态栏高度（单位：像素），获取失败返回 0
     */
    public float getNoticationBarHeight(Context context) {
        // 方法一：API 30+（Android 11+）推荐方案
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            try {
                // 获取窗口管理器
                WindowManager windowManager = SystemServiceUtil.getWindowManager();
                if (windowManager != null) {
                    // 获取当前窗口的 metrics（包含 insets）
                    WindowMetrics windowMetrics = windowManager.getCurrentWindowMetrics();
                    WindowInsets insets = windowMetrics.getWindowInsets();
                    // 提取状态栏的 insets（top 即为高度）
                    Insets statusBarRect = insets.getInsets(WindowInsets.Type.statusBars());
                    return statusBarRect.top;
                }
            } catch (Exception ignored) {
            }
        }

        // 方法二：反射获取系统资源（兼容 API 16+）
        try {
            @SuppressLint("PrivateApi") Class<?> clazz = Class.forName("com.android.internal.R$dimen");
            Object obj = clazz.newInstance();
            java.lang.reflect.Field field = clazz.getField("status_bar_height");
            int resId = Integer.parseInt(Objects.requireNonNull(field.get(obj)).toString());
            return getResources().getDimensionPixelSize(resId);
        } catch (Exception ignored) {
        }

        // 方法三：通过 Activity 的 DecorView 计算（兼容 API 14+）
        if (context instanceof android.app.Activity activity) {
            View decorView = activity.getWindow().getDecorView();
            Rect rect = new Rect();
            // 获取可见区域（不含状态栏）
            decorView.getWindowVisibleDisplayFrame(rect);
            // 状态栏高度 = 可见区域顶部坐标（通常为 0 或状态栏高度）
            return rect.top;
        }

        // 方法四：备选方案（通过屏幕尺寸计算）
        try {
            // 获取屏幕总高度（包含状态栏）
            DisplayMetrics displayMetrics = new DisplayMetrics();
            WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            windowManager.getDefaultDisplay().getRealMetrics(displayMetrics);
            int totalHeight = displayMetrics.heightPixels;

            // 获取应用可用区域高度（不含状态栏）
            displayMetrics = context.getResources().getDisplayMetrics();
            int appHeight = displayMetrics.heightPixels;

            // 计算状态栏高度
            return totalHeight - appHeight;
        } catch (Exception ignored) {
        }

        return 0f;
    }


    //-------------------------

    /**
     * dp 转 px
     *
     * @param dpValue dp值
     * @return 对应的px值（四舍五入）
     */
    public int dp2px(float dpValue) {
        float density = getScaledDensity();
        return (int) (dpValue * density + 0.5f);
    }

    /**
     * px 转 dp
     *
     * @param pxValue px值
     * @return 对应的dp值（四舍五入）
     */
    public int px2dp(float pxValue) {
        float density = getScaledDensity();
        return (int) (pxValue / density + 0.5f);
    }

    /**
     * sp 转 px（受系统字体缩放影响）
     *
     * @param spValue sp值
     * @return 对应的px值（四舍五入）
     */
    public int sp2px(float spValue) {
        float scaledDensity = getScaledDensity();
        return (int) (spValue * scaledDensity + 0.5f);
    }

    /**
     * px 转 sp（受系统字体缩放影响）
     *
     * @param pxValue px值
     * @return 对应的sp值（四舍五入）
     */
    public int px2sp(float pxValue) {
        float scaledDensity = getScaledDensity();
        return (int) (pxValue / scaledDensity + 0.5f);
    }

    /**
     * pt 转 px（pt是物理单位，1pt = 1/72英寸）
     *
     * @param ptValue pt值
     * @return 对应的px值（四舍五入）
     */
    public int pt2px(float ptValue) {
        DisplayMetrics metrics = getDisplayMetrics();
        float xdpi = metrics.xdpi; // 水平方向每英寸像素数
        // 1pt = (xdpi / 72) px（1英寸=72pt，因此1pt对应英寸占比是1/72）
        return (int) (ptValue * (xdpi / 72f) + 0.5f);
    }

    /**
     * px 转 pt
     *
     * @param pxValue px值
     * @return 对应的pt值（四舍五入）
     */
    public int px2pt(float pxValue) {
        DisplayMetrics metrics = getDisplayMetrics();
        float xdpi = metrics.xdpi;
        return (int) (pxValue * 72f / xdpi + 0.5f);
    }

    /**
     * pt 转 sp（先转px，再转sp）
     *
     * @param ptValue pt值
     * @return 对应的sp值（四舍五入）
     */
    public int pt2sp(float ptValue) {
        int px = pt2px(ptValue);
        return px2sp(px);
    }

    /**
     * sp 转 pt（先转px，再转pt）
     *
     * @param spValue sp值
     * @return 对应的pt值（四舍五入）
     */
    public int sp2pt(float spValue) {
        int px = sp2px(spValue);
        return px2pt(px);
    }

    /**
     * dp 转 sp（先转px，再转sp）
     *
     * @param dpValue dp值
     * @return 对应的sp值（四舍五入）
     */
    public int dp2sp(float dpValue) {
        int px = dp2px(dpValue);
        return px2sp(px);
    }

    /**
     * sp 转 dp（先转px，再转dp）
     *
     * @param spValue sp值
     * @return 对应的dp值（四舍五入）
     */
    public int sp2dp(float spValue) {
        int px = sp2px(spValue);
        return px2dp(px);
    }
    //-------------------------

    public float getScaledDensity() {
        return getDisplayMetrics().scaledDensity;
    }

    public DisplayMetrics getDisplayMetrics() {
        return getResources().getDisplayMetrics();
    }

    private Resources getResources() {
        return ContextUtil.getResources();
    }
}
